package com.wei.czz.framework.index.controller;

import com.wei.czz.common.annotation.Resubmit;
import com.wei.czz.common.constant.Constant;
import com.wei.czz.common.dto.index.login.CaptchaDto;
import com.wei.czz.common.dto.index.login.LoginDto;
import com.wei.czz.common.dto.admin.userRisk.UserRiskDto;
import com.wei.czz.common.enums.ResultEnum;
import com.wei.czz.common.enums.admin.user.RequestChannelEnum;
import com.wei.czz.common.tool.Result;
import com.wei.czz.common.utils.ContextUtils;
import com.wei.czz.common.utils.RegexUtils;
import com.wei.czz.common.vo.index.sign.FastLoginVo;
import com.wei.czz.common.vo.index.sign.FindPwdVo;
import com.wei.czz.common.vo.index.sign.PwdLoginVo;
import com.wei.czz.framework.index.manager.UserLoginManager;
import lombok.AllArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.Objects;

/**
 * Created by IntelliJ IDEA.
 *
 * @author wei
 * date: 2021-02-26 15:56:00
 * className: LoginController 用户登录请求接口类
 * version: 1.0
 * description:
 */
@RestController
@RequestMapping("/index")
@AllArgsConstructor
public class LoginController {

    private static final Logger log = LoggerFactory.getLogger(LoginController.class);

    private final UserLoginManager userLoginManager;

    /**
     * 获取图片验证码接口
     * <p>
     * 调用方：
     *  1、浏览器-用户登录页面调用
     */
    @GetMapping("/captcha")
    public Result<CaptchaDto> getCaptcha() {
        log.info("开始获取图片验证码业务");

        CaptchaDto captchaDto  = userLoginManager.getImageCaptcha();

        log.info("获取图片验证码业务结束");
        return Result.success(captchaDto);
    }

    /**
     * 发送免密登录验证码接口
     * @param contact   联系方式
     * @return 结果
     */
    @GetMapping("/send/login-code")
    public Result<Object> sendLoginCode(@RequestParam("contact") String contact) {
        log.info("开始发送登录短信验证码业务。contact={}", contact);

        // 判断联系方式是不是手机号或邮箱号
        if (!RegexUtils.isPhone(contact) && !RegexUtils.isEmail(contact)) {
            log.info("发送免密登录验证码，联系方式不是手机号或邮箱号");
            return Result.clientFail("请输入正确的手机号或邮箱号进行登录");
        }

        userLoginManager.sendLoginCode(contact);

        log.info("发送登录短信验证码业务结束");
        return Result.success();
    }

    /**
     * 发送找回密码验证码接口
     * @param contact   联系方式
     * @return 结果
     */
    @GetMapping("/send/find-password-code")
    public Result<Object> sendFindPasswordCode(@RequestParam("contact") String contact) {
        log.info("开始发送找回密码验证码业务。contact={}", contact);

        // 判断联系方式是不是手机号或邮箱号
        if (!RegexUtils.isPhone(contact) && !RegexUtils.isEmail(contact)) {
            log.info("发送找回密码验证码，联系方式不是手机号或邮箱号");
            return Result.clientFail("请输入正确的手机号或邮箱号");
        }

        userLoginManager.sendFindPasswordCode(contact);

        log.info("发送找回密码验证码业务结束");
        return Result.success();
    }

    /**
     * 用户密码登录接口
     * <p>
     * 调用方：
     *  1、浏览器-用户登录页面调用
     * <p>
     * 此接口会校验是否重复提交
     * @param pwdLoginVo 参数对象
     *
     */
    @Resubmit(spEL = "'passwordLogin' + #pwdLoginVo.loginName", message = "账号登录", resubmitTime = 2000)
    @PostMapping("/pwd/login")
    public Result<Object> passwordLogin(@Validated @RequestBody PwdLoginVo pwdLoginVo) {
        log.info("开始用户密码登录业务。{}", pwdLoginVo);

        String channel = ContextUtils.get(Constant.REQUEST_CHANNEL);
        // 获取请求渠道枚举对象
        RequestChannelEnum requestChannelEnum = RequestChannelEnum.get(channel);
        if (Objects.isNull(requestChannelEnum)) {
            log.info("密码登录，请求渠道枚举不存在。channel={}", channel);
            return Result.getResult(ResultEnum.ILLEGAL_FAIL.getCode(), "请求渠道不存在");
        }
        pwdLoginVo.setRequestChannelEnum(requestChannelEnum);

        LoginDto loginDto = userLoginManager.passwordLogin(pwdLoginVo);

        log.info("用户密码登录业务结束");
        return Result.success(loginDto);
    }

    /**
     * 用户免密登录接口
     * <p>
     * 调用方：
     *  1、浏览器-用户登录页面调用
     * <p>
     * 此接口会校验是否重复提交
     * @param fastLoginVo 参数对象
     * @return 请求结果
     */
    @Resubmit(spEL = "'fastLogin' + #fastLoginVo.contact", message = "免密登录", resubmitTime = 2000)
    @PostMapping("/fast/login")
    public Result<Object> fastLogin(@Validated @RequestBody FastLoginVo fastLoginVo) {
        log.info("开始用户免密登录业务。{}", fastLoginVo);

        // 判断联系方式是不是手机号或邮箱号
        if (!RegexUtils.isPhone(fastLoginVo.getContact()) && !RegexUtils.isEmail(fastLoginVo.getContact())) {
            log.info("免密登录，联系方式不是手机号或邮箱号");
            return Result.clientFail("请输入正确的手机号或邮箱号进行登录");
        }
        String channel = ContextUtils.get(Constant.REQUEST_CHANNEL);
        // 获取请求渠道枚举对象
        RequestChannelEnum requestChannelEnum = RequestChannelEnum.get(channel);
        if (Objects.isNull(requestChannelEnum)) {
            log.info("请求渠道枚举不存在。channel={}", channel);
            return Result.getResult(ResultEnum.ILLEGAL_FAIL.getCode(), "请求渠道不存在");
        }
        fastLoginVo.setRequestChannelEnum(requestChannelEnum);


        LoginDto loginDto = userLoginManager.fastLogin(fastLoginVo);

        log.info("用户免密登录业务结束");
        return Result.success(loginDto);
    }

    /**
     * 用户密码找回接口
     * <p>
     * 调用方：
     *  1、浏览器-用户登录页面调用
     * <p>
     * 此接口会校验是否重复提交
     * @param findPwdVo 参数对象
     * @return 请求结果
     */
    @Resubmit(spEL = "'findPassword' + #findPwdVo.contact", message = "找回密码")
    @PostMapping("/find/password")
    public Result<Object> findPassword(@Validated @RequestBody FindPwdVo findPwdVo) {
        log.info("开始用户密码找回业务。{}", findPwdVo);

        if (!RegexUtils.isPhone(findPwdVo.getContact()) && !RegexUtils.isEmail(findPwdVo.getContact())) {
            log.info("找回密码，联系方式不是手机号或邮箱号");
            return Result.clientFail("请输入正确的手机号或邮箱号进行密码找回");
        }

        userLoginManager.findPassword(findPwdVo);

        log.info("用户密码找回业务结束");
        return Result.success();
    }

    /**
     * 用户申诉登录接口
     * <p>
     * 调用方：
     *  1、浏览器-用户登录页面调用
     * <p>
     * 此接口会校验是否重复提交
     * @param pwdLoginVo 参数对象
     * @return 请求结果
     */
    @Resubmit(spEL = "'userAppealLogin' + #pwdLoginVo.loginName", message = "申诉登录")
    @PostMapping("/appeal/login")
    public Result<UserRiskDto> userAppealLogin(@Validated @RequestBody PwdLoginVo pwdLoginVo) {
        log.info("开始用户申诉登录业务。{}", pwdLoginVo);

        UserRiskDto userRiskDto = userLoginManager.appealLogin(pwdLoginVo);

        log.info("用户申诉登录业务结束");
        return Result.success(userRiskDto);
    }

    /**
     * 刷新token接口
     * <p>
     * 调用方：
     *  1、浏览器
     *
     * @param refreshToken 刷新token
     * @return 请求结果
     */
    @GetMapping("/refresh/token")
    public Result<LoginDto> refreshToken(@RequestParam("refreshToken") String refreshToken) {
        log.info("开始刷新token业务。refreshToken={}", refreshToken);

        // 从上下文参数中获取请求渠道
        String channel = ContextUtils.get(Constant.REQUEST_CHANNEL);
        RequestChannelEnum requestChannelEnum = RequestChannelEnum.get(channel);
        if (Objects.isNull(requestChannelEnum)) {
            log.info("请求渠道枚举不存在");
            return Result.getResult(ResultEnum.ILLEGAL_FAIL.getCode(), "请求渠道不存在");
        }

        LoginDto loginDto = userLoginManager.refreshToken(refreshToken, requestChannelEnum);

        log.info("刷新token业务结束");
        return Result.success(loginDto);
    }

}
